// use std::error;
use log::{info,error,warn};
use serialport::SerialPort;

use std::io::{BufRead, Read, Write};
pub use serialport;

pub struct Com{
    pub com:Box<dyn SerialPort>,
}
impl Com {
    pub fn new(com:Box<dyn SerialPort>)->Self{
        Self { com }
    }
    pub fn m_write(&mut self,cmd:&str)->std::io::Result<usize>{
        self.com.write(cmd.as_bytes())
    }
    pub fn m_read(&mut self)->Option<String>{
        let mut buff = [0;4096];
        let d = self.com.read(&mut buff).ok()?;
        let data = std::str::from_utf8(&buff[..d]).ok()?;
        info!("<-{data}");
        Some(data.to_string())
    }
    
    pub fn m_query(&mut self,cmd:&str)->Option<String>{
        self.m_write(cmd).ok()?;
        self.m_read()
    }
    // pub fn m_sendhex(&mut self,hex:&str)->std::io::Result<usize>{
    //     faster_hex::h
    //     self.com.write(buf)?
    // }
    pub fn m_confirmkey1s(&mut self,cmd:&str,key:&str)->std::io::Result<String>{
        self.m_write(cmd)?;
        info!("->{cmd}");
        let now = std::time::Instant::now();
        while now.elapsed()<std::time::Duration::from_secs(1){
            if let Some(d) = self.m_read(){
                if d.contains(key){
                    return Ok(d);
                }
            }
        }
        Err(std::io::ErrorKind::TimedOut.into())
    }
    pub fn m_write_bytes_line_key_timeout(&mut self,cmd:&[u8],key:&str,timeout:u64)->std::io::Result<String>{
        let mut allcount = cmd.len();
        let mut nn = self.com.write(cmd)?;
        while nn<allcount{
            allcount -=nn;
            nn = self.com.write(&cmd[..allcount])?;
        }
        let mut buff = [0;4096];
        let mut linecache = String::new();
        let now = std::time::Instant::now();
        while now.elapsed()<std::time::Duration::from_secs(timeout){
            if let Ok(n) = self.com.read(&mut buff){
                if let Ok(nn) = std::str::from_utf8(&buff[0..n]){
                    linecache.push_str(nn);
                    for iidx in linecache.lines(){
                        if iidx.contains(key){
                            info!("<-{iidx}");
                            return Ok(iidx.to_string());
                        }
                    }
                }
            }
            if now.elapsed()>std::time::Duration::from_secs(1){
                nn = self.com.write("\r\n\r\n\r\n".as_bytes())?;
            }
        }
        Err(std::io::ErrorKind::TimedOut.into())
    }
    pub fn m_confirm_line_key_timeout(&mut self,cmd:&str,key:&str,timeout:u64)->std::io::Result<String>{
        self.m_write(cmd)?;
        info!("->{cmd}");
        let mut buff = [0;4096];
        let now = std::time::Instant::now();
        while now.elapsed()<std::time::Duration::from_secs(timeout){
            if let Ok(n) = self.com.read(&mut buff){
                for idx in buff[0..n].lines(){
                    if let Ok(ss) = idx{
                        info!("<-{ss}");
                        if ss.contains(key){
                            return Ok(ss);
                        }
                    }
                }
            }
        }
        Err(std::io::ErrorKind::TimedOut.into())
    }
    pub fn m_sendwhilekeytimecount(&mut self,cmd:&str,key:&str,timeout:u64,count:usize)->std::io::Result<()>{
        for idx in 0..count{
            if self.m_confirm_line_key_timeout(cmd, key, timeout).is_ok(){
                return Ok(());
            }
        }
        Err(std::io::ErrorKind::TimedOut.into())
    }
}
#[test]
fn test1(){
    let mut dd = serialport::new("COM3", 115200).open().unwrap();
    let mut at = Com::new(dd);
    // dd.write(b"233");
}
// impl Chat for Atpack {
//     fn m_send(&mut self,cmd:&str,rn:bool)->std::io::Result<usize>{
//         match rn {
//             true => {
//                 let tosend = format!("{}\r\n",cmd);
//                 info!("->{}",tosend);
//                 self.write(tosend.as_bytes())
//             },
//             false => {info!("->{}",cmd);self.write(cmd.as_bytes())},
//         }
//     }
//     fn m_send_raw(&mut self,buf:&[u8])->std::io::Result<usize> {
//         info!("->hex:{}",faster_hex::hex_string_upper(&buf));
//         self.write(buf)
//     }
//     fn m_read(&mut self)->Option<String>{
//         // self.set_buffer_size(rx_size, tx_size)
//         let mut buff = [0;4096];
//         if let Ok(d)= self.read(&mut buff){
//             if let Ok(dd) = std::str::from_utf8(&buff[..d]){
//                 if dd.len()>0{
//                     info!("<-{dd}");
//                     return Some(dd.to_string());
//                 }
//             }else{
//                 error!("有数据解析错误");
//             }
//         }
//         None
//     }
//     fn m_read_logbin(&mut self,fl:&mut std::fs::File)->Option<String>{
//         // self.set_buffer_size(rx_size, tx_size)
//         let mut buff = [0;4096];
//         if let Ok(d)= self.read(&mut buff){
//             fl.write(&buff[..d]);
//             if let Ok(dd) = std::str::from_utf8(&buff[..d]){
//                 if dd.len()>0{
//                     return Some(dd.to_string());
//                 }
//             }else{
//                 println!("有数据解析错误");
//             }
//         }
//         None
//     }
//     fn m_read_n1(&mut self)->Option<String>{
//         let mut buff = String::new();
//         self.read_to_string(&mut buff).ok()?;
//         Some(buff)
//     }
//     fn m_query(&mut self,cmd:&str)->Option<String>{
//         self.m_send(cmd, true).ok()?;
//         self.m_read()
//     }

//     fn m_confirmkey(&mut self,cmd:&str,key:&str)->Option<String> {
//         if let Some(data) = self.m_query(cmd){
//             return data.contains(key).then_some(data)
//         }
//         None
//     }

//     fn m_rts(&mut self,level:bool)->Result<(),()> {
//         self.set_request_to_send(level).ok().ok_or(())?;
//         Ok(())
//     }

//     fn m_dtr(&mut self,level:bool)->Result<(),()> {
//         self.set_data_terminal_ready(level).ok().ok_or(())?;
//         Ok(())
//     }

//     fn m_cts(&mut self)->Result<bool,()> {
//         match  self.read_clear_to_send(){
//             Ok(level) => Ok(level),
//             Err(_) => Err(()),
//         }
//     }
//     fn m_ri(&mut self)->Result<bool,()>{
//         match self.read_ring_indicator(){
//             Ok(level) => Ok(level),
//             Err(_) => Err(()),
//         }
//     }

//     fn m_dcd(&mut self)->Result<bool,()> {
//         match self.read_carrier_detect(){
//             Ok(level) => Ok(level),
//             Err(_) => Err(()),
//         }
//     }

//     fn m_sendwhilekeytime(&mut self,cmd:&str,key:&str,timeout_s:u64)->std::io::Result<()> {
//         let nowtime = std::time::Instant::now();
//         loop{
//             if let Some(dd) = self.m_query(cmd){
//                 if dd.contains(key){
//                     return Ok(());
//                 }
//             };
//             std::thread::sleep(std::time::Duration::from_millis(1000));
//             if nowtime.elapsed()>std::time::Duration::from_secs(timeout_s){
//                 return Err(std::io::ErrorKind::TimedOut.into());
//             }
            
//         }
//     }
    
//     fn m_sendwhilekeytimecount(&mut self,cmd:&str,key:&str,timeout_s:u64,count:usize)->std::io::Result<()> {
//         let mut allcount = 0;
//         let nowtime = std::time::Instant::now();
//         loop{
//             if let Some(dd) = self.m_query(cmd){
//                 if dd.contains(key){
//                     allcount+=1;
//                     if allcount>count{
//                         return Ok(());
//                     }
//                 }
//             };
//             std::thread::sleep(std::time::Duration::from_millis(1000));
//             if nowtime.elapsed()>std::time::Duration::from_secs(timeout_s){
//                 return Err(std::io::ErrorKind::TimedOut.into());
//             }
            
//         }
//         todo!()
//     }

    


//     // fn m_confirmkey(&mut self,cmd:&str,key:&str)->Option<String,String>{

//     // }

// }

#[derive(Default)]
pub struct Atpack{
    porthandle:Option<Box<dyn serialport::SerialPort>>
}
// impl Chat for Atpack {
//     fn m_send(&mut self,data:&str,rn:bool)->std::io::Result<usize>{
//         if let Some(port) = &mut self.porthandle{
//             if rn{
//                 port.write(format!("{}\r\n",data).as_bytes())
//             }else{
//                 port.write(data.as_bytes())
//             }
//         }else{
//             Err(std::io::Error::from_raw_os_error(233))
//         }

//     }
//     fn m_read(&mut self)->Option<String>{
//         if let Some(port) = &mut self.porthandle{
//             let mut buff = [0;2048];
//             if let Ok(numc) = port.read(&mut buff){
//                 if let Ok(data) = std::str::from_utf8(&buff[..numc]){
//                     return Some(data.into());
//                 }
//             };
//         }
//         None
//     }
//     fn m_read_logbin(&mut self,fl:&mut std::fs::File)->Option<String>{
//         if let Some(port) = &mut self.porthandle{
//             let mut buff = [0;2048];
//             if let Ok(numc) = port.read(&mut buff){
//                 fl.write(&buff[..numc]);
//                 if let Ok(data) = std::str::from_utf8(&buff[..numc]){
//                     return Some(data.into());
//                 }
//             };
//         }
//         None
//     }
//     fn m_rts(&mut self,level:bool)->Result<(),()>{
//         if let Some(port) = &mut self.porthandle{
//             port.write_request_to_send(level).ok().ok_or(())?;
//             Ok(())
//         }else{
//             Err(())
//         }
//     }
//     fn m_dtr(&mut self,level:bool)->Result<(),()>{
//         if let Some(port) = &mut self.porthandle{
//             port.write_data_terminal_ready(level).ok().ok_or(())?;
//             Ok(())
//         }else{
//             Err(())
//         }
//     }
//     fn m_cts(&mut self)->Result<bool,()> {
//         if let Some(port) = &mut self.porthandle{
//             return match port.read_clear_to_send() {
//                 Ok(level) => Ok(level),
//                 Err(_) => Err(()),
//             }
//         }
//         Err(())
        
//     }
//     fn m_ri(&mut self)->Result<bool,()>{
//         if let Some(port) = &mut self.porthandle{
//             return match port.read_ring_indicator() {
//                 Ok(level) => Ok(level),
//                 Err(_) => Err(()),
//             };
//         }
//         Err(())
//     }

//     fn m_dcd(&mut self)->Result<bool,()> {
//         if let Some(port) = &mut self.porthandle {
//             return match port.read_carrier_detect() {
//                 Ok(level) => Ok(level),
//                 Err(_) => Err(()),
//             };
//         }
//         Err(())
//     }

//     fn m_read_n1(&mut self)->Option<String> {
//         None
//     }

//     fn m_query(&mut self,cmd:&str)->Option<String>{
//         self.m_send(cmd, true).ok()?;
//         self.m_read()
//     }

//     fn m_confirmkey(&mut self,cmd:&str,key:&str)->Option<String> {
//         if let Some(data) = self.m_query(cmd){
//             return data.contains(key).then_some(data)
//         }
//         None
//     }

//     fn m_sendwhilekeytime(&mut self,cmd:&str,key:&str,timeout_s:u64)->std::io::Result<()> {
//         let nowtime = std::time::Instant::now();
//         loop{
//             if let Some(dd) = self.m_query(cmd){
//                 info!("{}",dd);
//                 if dd.contains(key){
//                     return Ok(());
//                 }
//             };
//             if nowtime.elapsed()>std::time::Duration::from_secs(timeout_s){
//                 return Err(std::io::ErrorKind::TimedOut.into());
//             }
//         }
//     }

//     fn m_send_raw(&mut self,buf:&[u8])->std::io::Result<usize> {
//         // todo!()
//         Ok(2)
//     }

//     fn m_sendwhilekeytimecount(&mut self,cmd:&str,key:&str,timeout_s:u64,count:usize)->std::io::Result<()> {
//         Ok(())
//     }
    
//     // pub fn query(&mut self,msg:&str)->Option<String>{
//     //     if let Some(hand) =&mut self.porthandle{
//     //         if let Err(_) = hand.write(msg.as_bytes()){
//     //             return None;
//     //         };
//     //         let mut buff = [0;1024];
//     //         if let Ok(_) = hand.read(&mut buff){
//     //             if let Ok(data) = std::str::from_utf8(&buff[..]){
//     //                 return Some(data.into());
//     //             }
//     //         };
//     //     };
//     //     None
//     // }
//     // pub fn send_and_recv_confirm_single_key(&mut self,at_send:&str,at_recv:&str)->Result<String,String>{
//     //     let mut tmpdata = String::new();
//     //     if let Some(getdata) = self.query(at_send){
//     //         if let Some(_) = getdata.find(at_recv){
//     //             return Ok(getdata);
//     //         }
//     //         tmpdata = getdata;
//     //     }
//     //     Err(tmpdata)
//     // }
//     // pub fn send_and_recv_confirm_single_key_split_while(&mut self,at_send:&str,at_recv:&str,time_s:u64)->Result<String,String>{
//     //     let marktime = SystemTime::now();
//     //     let mut errmsg = String::new();
//     //     loop{
//     //         if let Some(data) = self.query(at_send){
//     //             let cc:Vec<&str> = data.split(",").collect();
//     //             for idx in cc{
//     //                 if let Some(_) = idx.find(at_recv){
//     //                     return Ok(data);
//     //                 }
//     //             }
//     //             errmsg = data;
//     //         }
//     //         if let Ok(tt) = marktime.elapsed(){
//     //             if tt>Duration::from_secs(time_s){
//     //                 return Err(errmsg);
//     //             }
//     //         };
//     //         sleep(Duration::from_secs(1));
//     //     }
//     // }
// }
// impl Atpack {
//     pub fn new()->Self{
//         Self{..Default::default()}
//     }
//     pub fn m_open(&mut self,compath:&str,boud:u32,tout:u64)->bool{
//         if let Ok(port) = serialport::new(compath, boud)
//         .timeout(std::time::Duration::from_millis(tout)).open(){
//             // let dd1 = Arc::new(Mutex::new(port));
//             // std::thread::spawn(move||{
//             //     unsafe{
//             //         dd1.as_ptr
//             //     }
//             // });
//             self.porthandle = Some(port);
//             return true;
//         };
//         false
//     }
    
// }


